/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2024-2024. All rights reserved.
 *
 */

import path from 'path';

import { MetricLogType, OutputFile, SubmitOption, TaskState } from '@ohos/hvigor';
import fse from 'fs-extra';

import { FileUtil } from '../utils/file-util.js';
import { OhosLogger } from '../utils/log/ohos-logger.js';
import { AbstractNativeStrip } from './abstract/abstract-native-strip.js';
import { TaskNames } from './common/task-names.js';
import { ProcessLibs } from './process-libs.js';
import { TargetTaskService } from './service/target-task-service.js';
import { strip, StripOptions, clearExpiredSoInStrippedDir } from './worker/native-strip.js';

export class DoNativeStrip extends AbstractNativeStrip {
  private _log: OhosLogger = OhosLogger.getLogger(DoNativeStrip.name);
  @OutputFile({ isDirectory: true }) private get doStrippedNativeLibs(): string {
    return this.strippedNativeLibs;
  }

  constructor(targetService: TargetTaskService) {
    super(targetService, TaskNames.Task.DO_NATIVE_STRIP);
  }


  protected async doTaskAction(): Promise<void> {
    // 确保 this.strippedNativeLibs 目录生成, 避免打包时 --lib-path 参数无效出错
    await fse.ensureDir(this.doStrippedNativeLibs);
    // 清除掉 this.strippedNativeLibs 目录中多余的 so 和软链接
    clearExpiredSoInStrippedDir(this.doStrippedNativeLibs, this.intermediatesProcessLibs);
    if (await FileUtil.isEmptyDir(this.intermediatesProcessLibs)) {
      // this.intermediatesProcessLibs 目录为空, 直接退出
      return;
    }

    const stripOptions: StripOptions = {
      debugSymbol: this.debugSymbol,
      strip: this.debugSymbol?.strip ?? true,
      exclude: this.exclude ?? [],
      intermediatesProcessLibs: this.intermediatesProcessLibs,
      sdkLlvmStripPath: this.sdkInfo.getSdkLlvmStrip(),
      strippedNativeLibs: this.doStrippedNativeLibs,
      moduleName: this.moduleName,
      taskName: this.name,
      cacheFilePath: this.cacheFilePath,
      lastCache: path.resolve(this.pathInfo.getIntermediatesPatch(), 'libs.json'),
      collectAllLibs: this.targetService.getBuildOption().nativeLib?.collectAllLibs,
    };
    const script: string = path.resolve(__dirname, './worker/native-strip.js/strip');
    const options: SubmitOption = {
      workInput: stripOptions,
    };
    if (this.getWorkerPool().submit(this, script, options).getState() === TaskState.REJECT) {
      const executeTaskName = 'strip native libs';
      const subExecuteDurationEvent = this.durationEvent.createSubEvent(executeTaskName, '');
      subExecuteDurationEvent.start();
      this._log.debug('Worker dispatch failed, running native strip on main thread.');
      await strip(stripOptions);
      subExecuteDurationEvent.stop();
      subExecuteDurationEvent.setLog(executeTaskName, MetricLogType.INFO);
    }
  }

  initTaskDepends(): void {
    this.declareDepends(ProcessLibs.name);
  }
}
